package tcp_proxy_router

import (
	"context"
	"fmt"
	"gitee.com/zhoulvvv/my_go_gateway/dao"
	"gitee.com/zhoulvvv/my_go_gateway/reverse_proxy"
	"gitee.com/zhoulvvv/my_go_gateway/services"
	"gitee.com/zhoulvvv/my_go_gateway/tcp_proxy_middleware"
	"gitee.com/zhoulvvv/my_go_gateway/tcp_server"
	"github.com/gin-gonic/gin"
	"log"
	"net"
	"net/http/httptest"
)

type tcpHandler struct {
}

func (t *tcpHandler) ServeTCP(ctx context.Context, src net.Conn) {
	src.Write([]byte("tcpHandler\n"))
}

var tcpServerList = []*tcp_server.TcpServer{}

func TcpServerRun() {
	// 获取TCP服务信息
	tcpServiceList := services.ServiceManagerServiceHandler.GetTcpServiceList(nil)
	for _, serviceItem := range tcpServiceList {
		tempItem := serviceItem
		log.Printf(" [INFO] tcp_proxy_run:%v\n", tempItem.TCPRule.Port)
		// 使用协程启动TCP服务
		go func(serviceInfo *dao.ServiceDetail) {
			c, _ := gin.CreateTestContext(httptest.NewRecorder())
			rb, err := services.LoadBalancerHandler.GetLoadBalancer(c, serviceInfo)
			if err != nil {
				log.Fatalf(" [ERROR] tcp_proxy_run【获取负载均衡器失败】 port：%v err：%v\n", serviceInfo.TCPRule.Port, err)
			}
			// 构建路由
			router := tcp_proxy_middleware.NewTcpSliceRouter()
			router.Group("/").Use(
				tcp_proxy_middleware.TCPFlowCountModeMiddleware(), // 服务统计
				tcp_proxy_middleware.TCPFlowLimitModeMiddleware(), // 服务限流
				tcp_proxy_middleware.TCPWhiteListModeMiddleware(), // IP 白名单
				tcp_proxy_middleware.TCPBlackListModeMiddleware(), // IP 黑名单
			)
			// 构建回调
			routerHandler := tcp_proxy_middleware.NewTcpSliceRouterHandler(func(c *tcp_proxy_middleware.TcpSliceRouterContext) tcp_server.TCPHandler {
				// 设置核心中间件，反向代理中间件
				return reverse_proxy.NewTcpLoadBalanceReverseProxy(c, rb)
			}, router)
			addr := fmt.Sprintf(":%d", serviceInfo.TCPRule.Port)
			// 把服务信息设置到上下文中
			baseCtx := context.WithValue(context.Background(), "service", serviceInfo)
			tcpServer := &tcp_server.TcpServer{
				Addr:    addr,
				Handler: routerHandler,
				BaseCtx: baseCtx,
			}
			tcpServerList = append(tcpServerList, tcpServer)
			// 运行服务器
			if err := tcpServer.ListenAndServe(); err != nil && err != tcp_server.ErrServerClosed {
				log.Fatalf(" [ERROR] tcp_proxy_run port：%v err：%v\n", serviceInfo.TCPRule.Port, err)
			}
		}(tempItem)
	}
}

func TcpServerStop() {
	for _, tcpServer := range tcpServerList {
		tcpServer.Close()
		log.Printf(" [INFO] tcp_proxy_stop stopped port %v\n", tcpServer.Addr)
	}
}
